//
//  KKTimer.m
//  PhnixHome
//
//  Created by Levy Xu on 2017/12/20.
//  Copyright © 2017年 Levy Xu. All rights reserved.
//

#import "KKTimer.h"

@interface KKTimer()
@property (strong, nonatomic) dispatch_source_t timer;
@property(nonatomic, assign) BOOL valid;
@end

@implementation KKTimer

+(KKTimer *)once:(NSTimeInterval)interval task:(void (^)(NSUInteger times))task {
    return [KKTimer every:interval repeat:1 task:task];
}

+(KKTimer *)every:(NSTimeInterval)interval task:(void (^)(NSUInteger times))task {
    return [KKTimer every:interval repeat:NSUIntegerMax task:task];
}

+(KKTimer *)every:(NSTimeInterval)interval repeat:(NSUInteger)repeat task:(void (^)(NSUInteger times))task {
    return [[self alloc] initWithInterval:interval repeat:repeat task:task];
}

- (instancetype)initWithInterval:(NSTimeInterval)interval repeat:(NSUInteger)repeat task:(void (^)(NSUInteger times))task {
    self = [super init];
    if (self) {
        _interval = interval;
        
        self.valid = YES;
        WS(ws);
        __block int jishi = 0;
        self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
        dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0);
        dispatch_source_set_event_handler(self.timer, ^{
            task(++jishi);
            if (repeat <= jishi) {
                ws.valid = NO;
                dispatch_source_cancel(ws.timer);
            }
        });
        dispatch_resume(self.timer);
    }
    return self;
}

-(void)setInterval:(NSTimeInterval)interval {
    _interval = interval;
    
    dispatch_suspend(self.timer);
    dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0);
    dispatch_resume(self.timer);
}

-(void)fire {
    dispatch_suspend(self.timer);
    dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, 0), _interval * NSEC_PER_SEC, 0);
    dispatch_resume(self.timer);
}

- (void)dealloc {
    [self invalidate];
}

- (void)invalidate {
    self.valid = NO;
    if (self.timer) {
        dispatch_source_cancel(self.timer);
    }
}

@end
